/**
 * 
 */
package edu.umd.clip.smoothing;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class KNSmoother extends Smoother {
	private final double D;
	private final double backoffProb;
	private final double revTotalCount;
	
	public KNSmoother(SmootherProducer producer) {
		super(producer);
		revTotalCount = 1.0 / totalCount;
		int counts[] = producer.getCounts();
		int N1 = counts[1];
		int N2 = counts[2];
		if (N1 == 0 || N2 == 0) {
			backoffProb = Double.NaN;
			D = 0;
		} else {
			D = (double) (N1) / (N1 + 2*N2);
			assert(D > 0 && D <= 1.0);
			long N1plus = 0;
			for(int i=1; i<counts.length; ++i) {
				N1plus += counts[i];
			}
			backoffProb = (D * N1plus) * revTotalCount;
		}
		System.out.printf("KN: D=%g, backoff=%g, N1=%d, N2=%d count=%d\n", D, backoffProb, N1, N2, producer.getTotalCount());
	}
	/* (non-Javadoc)
	 * @see edu.umd.clip.smoothing.Smoother#getBackoffProb()
	 */
	public double getBackoffProb() {
		return backoffProb;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.smoothing.Smoother#getProb(long)
	 */
	public double getProb(long count) {
		if (count < minCount) return 0.0; 
		return (count - D) * revTotalCount;
	}
	@Override
	public String toString() {
		return String.format("KN Smoother (D=%g, bo=%g, count=%d)", D, backoffProb, totalCount);
	}
}
